
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using GruntXProductions;
using Viper;
using Viper.Opcodes;

namespace Diamond
{
	public partial class CodeGen 
	{
		public void GetIntegerValue(SyntaxNode sn)
		{
			if(sn is IntLiteral)
			{
				Assembler.Emit(new push_d((uint)((IntLiteral)sn).Value));
			}
			else if (sn is SymbolRef)
			{
				if(Symbols[((SymbolRef)sn).Value] == "")
					Errors.Add(((SymbolRef)sn).Value + " does not exist in the current context!");
				else if (Symbols.GetType(((SymbolRef)sn).Value) != VType.Dword)
					Errors.Add(((SymbolRef)sn).Value + " can not be converted to type int!");
				else
				{
					Assembler.Emit(new push_ptr(Symbols[((SymbolRef)sn).Value]));
					Assembler.Emit(new dload());
				}
			}
			else if (sn is FunctionCall)
			{
				FunctionCall fc = sn as FunctionCall;
				if(GetReturnType(fc) != "int")
					Errors.Add("Method " + fc.Target + " does not return type int!");
				else
					Call(fc);
			}
			else if (sn is Ref)
			{
				Ref r = sn as Ref;
				Assembler.Emit(new push_ptr(Symbols[r.Symbol]));
			}
			else if (sn is Expression)
			{
				ParseArthemeticExpression(sn as Expression);
			}
		}
		
		public void ParseArthemeticExpression(Expression exp)
		{
			foreach(SyntaxNode sn in exp.Items)
			{
				if(sn is Operator)
				{
					Operator op = sn as Operator;
					if(isOverloaded(op, "int"))
						CallOperator(op, getOverload(op, "int"));
					else
					{
						GetIntegerValue(op.Op1);
						GetIntegerValue(op.Op2);
						if(sn is Plus)
							Assembler.Emit(new Add());
						else if(sn is Multiply)
							Assembler.Emit(new mul_s());
						else if(sn is Subtract)
							Assembler.Emit(new sub());
						else if (sn is Divide)
							Assembler.Emit(new div_s());
						else if (sn is LeftBitshift)
							Assembler.Emit(new shl());
						else if (sn is RightBitshift)
							Assembler.Emit(new shr());
						else
							Errors.Add("Operator '" + op.theOperator + "' can not be applied between int");
					}
				}
				else
				{
					GetIntegerValue(sn);
				}
			}
		}
		
		public void ParseUnsignedArthemeticExpression(Expression exp)
		{
			foreach(SyntaxNode sn in exp.Items)
			{
				if(sn is Operator)
				{
					Operator op = sn as Operator;
					if(isOverloaded(op, "uint"))
					{
						CallOperator(op, getOverload(op, "uint"));
					}
					else
					{
						GetIntegerValue(op.Op1);
						GetIntegerValue(op.Op2);
						if(sn is Plus)
							Assembler.Emit(new Add());
						else if(sn is Multiply)
							Assembler.Emit(new mul());
						else if(sn is Subtract)
							Assembler.Emit(new sub());
						else if (sn is Divide)
							Assembler.Emit(new div());
						else if (sn is LeftBitshift)
							Assembler.Emit(new shl());
						else if (sn is RightBitshift)
							Assembler.Emit(new shr());
						else
							Errors.Add("Operator '" + op.theOperator + "' can not be applied to type uint");
					}
				}
				else
				{
					GetIntegerValue(sn);
				}
			}
		}
	}
	
}